"""
OLED 显示插件 - MicroPython ESP32
版本: 2.1 (智能模式切换)
硬件: SSD1306 128x32 OLED
功能: 自动模式切换（表情模式 vs 文字模式）
"""

import uasyncio as asyncio
import gc
import time
from machine import Pin, I2C, RTC
import sys
import _thread

sys.path.append('/plugins/base')
from plugin import Plugin

# ==================== 表情管理器 ====================
class EmotionManager:
    """表情管理器 - 32x32像素表情库"""
    
    EMOTIONS = {
        'happy': [  # 😊 开心
            "     ******     ",
            "   **      **   ",
            "  *          *  ",
            " *   **  **   * ",
            " *   **  **   * ",
            "*              *",
            "*   *      *   *",
            "*    ******    *",
            " *            * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ],
        'sad': [  # 😢 伤心
            "     ******     ",
            "   **      **   ",
            "  *          *  ",
            " *   **  **   * ",
            " *   **  **   * ",
            "*              *",
            "*              *",
            "*    ******    *",
            " *   *    *   * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ],
        'angry': [  # 😠 生气
            "     ******     ",
            "   **      **   ",
            "  * **    ** *  ",
            " *  **    **  * ",
            " *   **  **   * ",
            "*              *",
            "*   ******     *",
            "*              *",
            " *    ****    * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ],
        'surprise': [  # 😲 惊讶
            "     ******     ",
            "   **      **   ",
            "  *   **  *  *  ",
            " *   ****    * * ",
            " *   **  **   * ",
            "*              *",
            "*      **      *",
            "*     ****     *",
            " *     **     * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ],
        'love': [  # 😍 爱心
            "     ******     ",
            "   **      **   ",
            "  * ** **  *  * ",
            " * **** **** * *",
            " *  *** ***   * ",
            "*   *******    *",
            "*    *****     *",
            "*     ***      *",
            " *     *      * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ],
        'cool': [  # 😎 酷
            "     ******     ",
            "   **      **   ",
            "  *          *  ",
            " * ********* * *",
            " * ***   *** * *",
            "*              *",
            "*              *",
            "*   *******    *",
            " *            * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ],
        'sleep': [  # 😴 睡觉
            "     ******     ",
            "   **      **   ",
            "  *          *  ",
            " *   **  **   * ",
            " *              ",
            "*      **      *",
            "*              *",
            "*   ********   *",
            " *            * ",
            "  *    zZ    *  ",
            "   ** zZzZ **   ",
            "     ******     "
        ],
        'think': [  # 🤔 思考
            "     ******     ",
            "   **      **   ",
            "  *    **    *  ",
            " *    ****    * ",
            " *   **  **   * ",
            "*              *",
            "*       **     *",
            "*      ****    *",
            " *      **    * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ],
        'wink': [  # 😉 眨眼
            "     ******     ",
            "   **      **   ",
            "  *          *  ",
            " *   **  **   * ",
            " *         **  *",
            "*              *",
            "*   *******    *",
            "*              *",
            " *            * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ],
        'laugh': [  # 😄 大笑
            "     ******     ",
            "   **      **   ",
            "  *          *  ",
            " *   **  **   * ",
            " *   **  **   * ",
            "*    ******    *",
            "*   **    **   *",
            "*              *",
            " *  ********  * ",
            "  *          *  ",
            "   **      **   ",
            "     ******     "
        ]
    }
    
    @staticmethod
    def render_emotion(display, emotion_name, x=0, y=0):
        """渲染表情到显示器"""
        if emotion_name not in EmotionManager.EMOTIONS:
            emotion_name = 'happy'
        
        pattern = EmotionManager.EMOTIONS[emotion_name]
        y_offset = 4  # 垂直居中
        
        for row_idx, row in enumerate(pattern):
            for col_idx, char in enumerate(row):
                if char == '*':
                    px = x + col_idx * 2
                    py = y + y_offset + row_idx * 2
                    display.fill_rect(px, py, 2, 2, 1)
    
    @staticmethod
    def get_emotion_list():
        """获取所有表情名称"""
        return list(EmotionManager.EMOTIONS.keys())

# ==================== OLED 插件 ====================
class OLED(Plugin):
    """
    OLED 显示插件 - 智能模式切换
    模式1: 表情模式（左表情32px + 右时钟96px）
    模式2: 文字模式（全屏显示文字）
    """
    
    # 硬件配置
    I2C_SCL_PIN = 8
    I2C_SDA_PIN = 9
    I2C_FREQ = 400000
    
    OLED_WIDTH = 128
    OLED_HEIGHT = 32
    OLED_ADDR = 0x3C
    
    FONT_FILE = "/unifont-16.v3.bmf"
    
    # 表情模式布局
    EMOTION_WIDTH = 32
    CLOCK_X = 34  # 表情宽度 + 间隙
    CLOCK_WIDTH = 94  # 128 - 34
    
    def __init__(self, loader):
        super().__init__(loader, "OLED", enabled=True)
        self.capabilities = ["display", "oled", "emotion", "smart_mode"]
        
        self.run_in_thread = True
        
        # 硬件对象
        self.display = None
        self.font = None
        self.i2c = None
        self.rtc = None
        
        # 显示模式
        self.display_mode = 'text'  # 'text' 或 'emotion'
        
        # 表情模式状态
        self.current_emotion = 'happy'
        self.clock_format_24h = True
        
        # 文字模式状态
        self.text_content = ''
        self.text_x = 0
        self.text_y = 0
        self.text_font_size = 16
        self.text_wrap = True
        self.text_spacing = 2
        
        # 控制变量
        self.queue_lock = None
        self.display_queue = []
        self.should_render = True
        self.last_render_time = 0
        self.last_clock_update = 0
        
        self.display_errors = 0
        self.max_display_errors = 3
    
    async def _do_init(self):
        """初始化插件"""
        try:
            # 1. 初始化 I2C
            self.logger.info("初始化I2C")
            self.i2c = I2C(
                scl=Pin(self.I2C_SCL_PIN),
                sda=Pin(self.I2C_SDA_PIN),
                freq=self.I2C_FREQ
            )
            
            devices = self.i2c.scan()
            self.logger.debug("I2C设备: %s" % [hex(d) for d in devices])
            
            if self.OLED_ADDR not in devices:
                self.logger.error("未找到OLED (0x%02X)" % self.OLED_ADDR)
                return False
            
            # 2. 初始化 OLED
            self.logger.info("初始化显示器")
            try:
                import ssd1306
                self.display = ssd1306.SSD1306_I2C(
                    self.OLED_WIDTH,
                    self.OLED_HEIGHT,
                    self.i2c,
                    addr=self.OLED_ADDR
                )
            except ImportError:
                self.logger.error("ssd1306库未安装")
                return False
            
            # 3. 加载字体
            try:
                import ufont
                self.font = ufont.BMFont(self.FONT_FILE)
                self.logger.info("字体加载成功")
            except Exception as e:
                self.font = None
                self.logger.warning("字体加载失败: %s" % e)
            
            # 4. 初始化 RTC
            try:
                self.rtc = RTC()
                self.logger.info("RTC初始化成功")
            except Exception as e:
                self.logger.warning("RTC初始化失败: %s" % e)
            
            # 5. 初始化线程锁
            self.queue_lock = _thread.allocate_lock()
            
            # 6. 初始化显示
            self.display.fill(0)
            self.display.show()
            
            # 7. 显示启动消息
            await asyncio.sleep_ms(100)
            self.text_content = '葵宝启动'
            self.display_mode = 'text'
            self.should_render = True
            
            # 8. 注册命令
            self.loader.register_command('display', self._handle_display_command)
            self.loader.register_command('display_clear', self._handle_clear_command)
            self.loader.register_command('display_emotion', self._handle_emotion_command)
            self.loader.register_command('display_mode', self._handle_mode_command)
            self.loader.register_command('display_time', self._handle_time_command)
            
            await self.send_log('info', 'OLED初始化成功（智能模式）')
            
            gc.collect()
            return True
            
        except Exception as e:
            self.logger.error("初始化失败: %s" % e)
            if hasattr(self.loader, 'config') and self.loader.config.DEBUG_MODE:
                sys.print_exception(e)
            return False
    
    def thread_run(self):
        """线程主循环"""
        self.logger.info("OLED线程开始运行")
        
        while self.running and self.enabled:
            try:
                now = time.ticks_ms()
                has_work = False
                
                # 1. 处理显示队列
                task = None
                try:
                    if self.queue_lock and self.queue_lock.acquire(0):
                        try:
                            if self.display_queue:
                                task = self.display_queue.pop(0)
                                has_work = True
                        finally:
                            self.queue_lock.release()
                except:
                    pass
                
                if task:
                    self._process_display_task(task)
                    self.should_render = True
                
                # 2. 表情模式下更新时钟
                if self.display_mode == 'emotion':
                    if time.ticks_diff(now, self.last_clock_update) > 1000:
                        self.last_clock_update = now
                        self.should_render = True
                        has_work = True
                
                # 3. 渲染
                if self.should_render or time.ticks_diff(now, self.last_render_time) > 100:
                    self._render_display()
                    self.last_render_time = now
                    self.should_render = False
                    has_work = True
                
                # 4. 休眠
                if has_work:
                    time.sleep_ms(10)
                else:
                    time.sleep_ms(50)
                
            except Exception as e:
                self.logger.error("线程错误: %s" % e)
                time.sleep_ms(100)
        
        self.logger.info("OLED线程已停止")
    
    def _render_display(self):
        """根据当前模式渲染显示内容"""
        if not self.display:
            return
        
        try:
            self.display.fill(0)
            
            if self.display_mode == 'emotion':
                # 表情模式：左表情 + 右时钟
                self._render_emotion_mode()
            else:
                # 文字模式：全屏文字
                self._render_text_mode()
            
            self.display.show()
            self.display_errors = 0
            
        except Exception as e:
            self.display_errors += 1
            self.logger.error("渲染失败: %s" % e)
            
            if self.display_errors >= self.max_display_errors:
                self.logger.critical("渲染失败次数过多")
                self.enabled = False
    
    def _render_emotion_mode(self):
        """渲染表情模式：左表情32px + 右时钟96px"""
        try:
            # 1. 渲染表情（左侧32px）
            EmotionManager.render_emotion(
                self.display,
                self.current_emotion,
                0, 0
            )
            
            # 2. 分隔线
            self.display.vline(self.EMOTION_WIDTH, 0, self.OLED_HEIGHT, 1)
            
            # 3. 渲染时钟（右侧）
            if self.rtc:
                self._render_clock()
            
        except Exception as e:
            self.logger.error("表情模式渲染失败: %s" % e)
    
    def _render_clock(self):
        """渲染时钟（垂直居中）"""
        try:
            dt = self.rtc.datetime()
            
            if self.clock_format_24h:
                time_str = "%02d:%02d:%02d" % (dt[4], dt[5], dt[6])
            else:
                hour = dt[4]
                ampm = "AM" if hour < 12 else "PM"
                hour = hour % 12
                if hour == 0:
                    hour = 12
                time_str = "%d:%02d %s" % (hour, dt[5], ampm)
            
            # 居中显示
            if self.font:
                try:
                    # 计算文本宽度（估算）
                    text_width = len(time_str) * 5
                    x = self.CLOCK_X + (self.CLOCK_WIDTH - text_width) // 2
                    y = (self.OLED_HEIGHT - 10) // 2
                    
                    self.font.text(
                        self.display,
                        time_str,
                        x, y,
                        color=1,
                        font_size=10,
                        show=False,
                        clear=False
                    )
                except:
                    # 字体渲染失败，使用默认字体
                    x = self.CLOCK_X + 10
                    y = 12
                    self.display.text(time_str[:10], x, y, 1)
            else:
                x = self.CLOCK_X + 10
                y = 12
                self.display.text(time_str[:10], x, y, 1)
                
        except Exception as e:
            self.logger.error("时钟渲染失败: %s" % e)
    
    def _render_text_mode(self):
        """渲染文字模式：全屏显示文字"""
        try:
            if not self.text_content:
                return
            
            if self.font:
                try:
                    self.font.text(
                        self.display,
                        self.text_content,
                        self.text_x,
                        self.text_y,
                        color=1,
                        bg_color=0,
                        font_size=self.text_font_size,
                        auto_wrap=self.text_wrap,
                        show=False,
                        clear=False,
                        line_spacing=self.text_spacing
                    )
                except Exception as e:
                    # 字体渲染失败，使用默认字体
                    self.logger.error("字体渲染失败: %s" % e)
                    self.display.text(self.text_content[:16], self.text_x, self.text_y, 1)
            else:
                # 没有字体，使用默认字体
                self.display.text(self.text_content[:16], self.text_x, self.text_y, 1)
                
        except Exception as e:
            self.logger.error("文字模式渲染失败: %s" % e)
    
    def _process_display_task(self, task):
        """处理显示任务"""
        try:
            task_type = task.get('type', 'text')
            
            if task_type == 'text':
                # 切换到文字模式
                self.display_mode = 'text'
                self.text_content = task.get('text', '')
                self.text_x = task.get('x', 0)
                self.text_y = task.get('y', 0)
                self.text_font_size = task.get('font_size', 16)
                self.text_wrap = task.get('wrap', True)
                self.text_spacing = task.get('spacing', 2)
                
                self.logger.info("文字模式: '%s'" % self.text_content)
                
            elif task_type == 'emotion':
                # 切换到表情模式
                self.display_mode = 'emotion'
                emotion = task.get('emotion', self.current_emotion)
                
                if emotion in EmotionManager.get_emotion_list():
                    self.current_emotion = emotion
                
                self.logger.info("表情模式: %s" % self.current_emotion)
            
        except Exception as e:
            self.display_errors += 1
            self.logger.error("任务处理失败: %s" % e)
    
    # ==================== 命令处理 ====================
    
    async def _handle_display_command(self, params):
        """处理display命令 - 全屏显示文字"""
        try:
            if not self.display:
                return {"success": False, "error": "显示器未初始化"}
            
            text = params.get('text', '')
            x = params.get('x', 0)
            y = params.get('y', 0)
            font_size = params.get('font_size', 16)
            wrap = params.get('wrap', True)
            spacing = params.get('spacing', 2)
            
            task = {
                'type': 'text',
                'text': text,
                'x': x,
                'y': y,
                'font_size': font_size,
                'wrap': wrap,
                'spacing': spacing
            }
            
            if self.queue_lock:
                with self.queue_lock:
                    self.display_queue.append(task)
            
            return {
                "success": True,
                "mode": "text",
                "message": "已切换到文字模式"
            }
            
        except Exception as e:
            self.logger.error("命令失败: %s" % e)
            return {"success": False, "error": str(e)}
    
    async def _handle_emotion_command(self, params):
        """处理表情命令 - 显示表情+时钟"""
        try:
            if not self.display:
                return {"success": False, "error": "显示器未初始化"}
            
            emotion = params.get('emotion', 'happy')
            
            emotions = EmotionManager.get_emotion_list()
            if emotion not in emotions:
                return {
                    "success": False,
                    "error": "未知表情",
                    "available": emotions
                }
            
            task = {
                'type': 'emotion',
                'emotion': emotion
            }
            
            if self.queue_lock:
                with self.queue_lock:
                    self.display_queue.append(task)
            
            return {
                "success": True,
                "mode": "emotion",
                "emotion": emotion,
                "message": "已切换到表情模式"
            }
            
        except Exception as e:
            self.logger.error("表情命令失败: %s" % e)
            return {"success": False, "error": str(e)}
    
    async def _handle_mode_command(self, params):
        """处理模式切换命令"""
        try:
            mode = params.get('mode', 'text')
            
            if mode not in ['text', 'emotion']:
                return {
                    "success": False,
                    "error": "无效模式",
                    "available": ['text', 'emotion']
                }
            
            task = {'type': mode}
            
            if mode == 'emotion':
                task['emotion'] = params.get('emotion', self.current_emotion)
            elif mode == 'text':
                task['text'] = params.get('text', self.text_content)
            
            if self.queue_lock:
                with self.queue_lock:
                    self.display_queue.append(task)
            
            return {
                "success": True,
                "mode": mode,
                "message": "模式已切换"
            }
            
        except Exception as e:
            self.logger.error("模式切换失败: %s" % e)
            return {"success": False, "error": str(e)}
    
    async def _handle_time_command(self, params):
        """处理时间设置"""
        try:
            if not self.rtc:
                return {"success": False, "error": "RTC未初始化"}
            
            format_24h = params.get('format_24h')
            if format_24h is not None:
                self.clock_format_24h = format_24h
            
            year = params.get('year')
            month = params.get('month')
            day = params.get('day')
            hour = params.get('hour')
            minute = params.get('minute')
            second = params.get('second', 0)
            
            if all(v is not None for v in [year, month, day, hour, minute]):
                weekday = 0
                self.rtc.datetime((year, month, day, weekday, hour, minute, second, 0))
                self.logger.info("时间已设置")
            
            self.should_render = True
            
            dt = self.rtc.datetime()
            return {
                "success": True,
                "time": {
                    "year": dt[0],
                    "month": dt[1],
                    "day": dt[2],
                    "hour": dt[4],
                    "minute": dt[5],
                    "second": dt[6],
                    "format_24h": self.clock_format_24h
                }
            }
            
        except Exception as e:
            self.logger.error("时间设置失败: %s" % e)
            return {"success": False, "error": str(e)}
    
    async def _handle_clear_command(self, params):
        """处理清屏"""
        try:
            if not self.display:
                return {"success": False, "error": "显示器未初始化"}
            
            self.text_content = ''
            self.should_render = True
            
            return {"success": True, "message": "清屏成功"}
            
        except Exception as e:
            self.logger.error("清屏失败: %s" % e)
            return {"success": False, "error": str(e)}
    
    async def handle_command(self, command, params):
        """命令路由"""
        handlers = {
            "display": self._handle_display_command,
            "display_clear": self._handle_clear_command,
            "display_emotion": self._handle_emotion_command,
            "display_mode": self._handle_mode_command,
            "display_time": self._handle_time_command
        }
        
        handler = handlers.get(command)
        if handler:
            return await handler(params)
        
        return None
    
    async def cleanup(self):
        """清理资源"""
        self.logger.info("开始清理OLED")
        
        if self.display:
            try:
                self.display.fill(0)
                self.display.show()
            except:
                pass
        
        self.display = None
        self.font = None
        self.i2c = None
        self.rtc = None
        
        await super().cleanup()
        self.logger.info("OLED清理完成")